/*!
  @file camera_driver.h
  @copyright 2013 Kubota Lab. All rights resereved.
*/

#ifndef _AXIS_CAMERA_DRIVER_H_
#define _AXIS_CAMERA_DRIVER_H_

#include <ros/ros.h>

#include <string>

#include <curl/curl.h>
#include <image_transport/image_transport.h>
#include <camera_info_manager/camera_info_manager.h>

namespace axis_netcam 
{

/*! 
 *  @brief  Image driver via HTTP request
 *  @author Kyohei Otsu <kyon@ac.jaxa.jp>
 *  @date   2013
 *  
 *
 */

class CameraDriver
{
 public:
  CameraDriver(const ros::NodeHandle &nh, const ros::NodeHandle &camera_nh, const ros::NodeHandle &private_nh=ros::NodeHandle("~"))
      : nh_(nh)
      , private_nh_(private_nh)
      , camera_nh_(camera_nh)
      , cinfo_(new camera_info_manager::CameraInfoManager(camera_nh_))
      , it_(nh_)
      , resolution_("1024x768")
  {
    /* initializing pub/sub, server */
    img_pub_ = it_.advertiseCamera(camera_nh_.resolveName("image_raw"), 1);

    /* initializing optional parameters */
    /*   e.g.) private_nh_.param<TYPE>("PARAM_NAME", PARAM_VAR, DEFAULT_VALUE);  */
    private_nh_.param<std::string>("camera_ipaddr", camera_ipaddr_, "192.168.0.1");
    nh_.param<double>("frame_rate", frame_rate_, 30.0); // tmp

    private_nh_.param<std::string>("camera_name", camera_name_, "camera");
    if (!cinfo_->setCameraName(camera_name_)) 
    {
      ROS_WARN_STREAM("name [" << camera_name_ << "] not valid");
    }

    ROS_INFO_STREAM("=========================================");

    std::string camera_info_url;
    private_nh_.param<std::string>("camera_info_url", camera_info_url, "");
    if (camera_info_url.length() > 0) cinfo_->loadCameraInfo(camera_info_url);

    resolution_ = (boost::format("%dx%d") %cinfo_->getCameraInfo().width %cinfo_->getCameraInfo().height).str();

    ROS_INFO_STREAM("Camera Setting");
    ROS_INFO_STREAM("    IP Address: " << camera_ipaddr_);
    ROS_INFO_STREAM("    Resolusion: " << resolution_);
    ROS_INFO_STREAM("    Frame Rate: " << frame_rate_);

    ROS_INFO_STREAM("=========================================");

    /* CameraDriver initialized! init() should be called now. */
  }

  ~CameraDriver() 
  { 
    curl_easy_cleanup(curl_);
    curl_global_cleanup();
    if (chunk_.memory)
    {
      free(chunk_.memory);
    }
    ROS_INFO("Successfully cleaned CameraDriver");
  }
  

  //! initializes html connection
  void init();

  //! fetch an image from the device
  int poll();

  //! start loop and publish images
  //!
  //! Do not use for nodelet. Use poll() instead.
  //! @param rate request rate in Hz
  void run();

  static size_t htmlCB(void *contents, size_t size, size_t nmemb, void *userp);

  double getFrameRate() { return frame_rate_; }


 private:
  struct MemoryStruct
  {
    char *memory;
    size_t size;
  };

  

  ros::NodeHandle nh_;
  ros::NodeHandle private_nh_;
  ros::NodeHandle camera_nh_;
  std::string camera_name_;
  boost::shared_ptr<camera_info_manager::CameraInfoManager> cinfo_;
  image_transport::ImageTransport it_;
  image_transport::CameraPublisher img_pub_;

  CURL *curl_;
  std::string camera_ipaddr_;
  std::string resolution_;
  double frame_rate_;
  MemoryStruct chunk_;
  std::string url_;
};

}  // namespace axis_netcam

#endif

